/*
Copyright (c) 2025 HeZongLun
NahidaProject is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan
PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/

#pragma once

#ifdef _WIN32
#define ExportSymbol  __declspec(dllexport)
#else
#define ExportSymbol
#endif

#include <iostream>
#include <string>
#include <regex>
#include <vector>
#include <functional>
#include <map>
#include <algorithm>
#include <cctype>

namespace NahidaProject {
	class ExportSymbol StringValidator {
	public:
		enum class ExportSymbol ValidationType {
			EMAIL,
			PHONE,
			URL,
			IP_ADDRESS,
			MAC_ADDRESS,
			DATE,
			TIME,
			DATETIME,
			NUMBER,
			INTEGER,
			FLOAT,
			HEX,
			BASE64,
			UUID,
			CREDIT_CARD,
			POSTAL_CODE,
			CUSTOM
		};

		struct ExportSymbol ValidationResult {
			bool isValid;
			std::string errorMessage;

			ValidationResult(bool valid = false, const std::string& error = "") : isValid(valid), errorMessage(error) {

			}
		};

	private:
		std::map<ValidationType, std::string> regexPatterns = {
			{ValidationType::EMAIL, R"(^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$)"},
			{ValidationType::PHONE, R"(^(\+?86)?1[3-9]\d{9}$)"},
			{ValidationType::URL, R"(^(https?|ftp)://[^\s/$.?#].[^\s]*$)"},
			{ValidationType::IP_ADDRESS, R"(^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$)"},
			{ValidationType::MAC_ADDRESS, R"(^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$)"},
			{ValidationType::DATE, R"(^\d{4}-\d{2}-\d{2}$)"},
			{ValidationType::TIME, R"(^([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$)"},
			{ValidationType::DATETIME, R"(^\d{4}-\d{2}-\d{2} ([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$)"},
			{ValidationType::NUMBER, R"(^-?\d+(\.\d+)?$)"},
			{ValidationType::INTEGER, R"(^-?\d+$)"},
			{ValidationType::FLOAT, R"(^-?\d+\.\d+$)"},
			{ValidationType::HEX, R"(^0x[0-9A-Fa-f]+$)"},
			{ValidationType::BASE64, R"(^[A-Za-z0-9+/]*={0,2}$)"},
			{ValidationType::UUID, R"(^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$)"},
			{ValidationType::CREDIT_CARD, R"(^\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}$)"},
			{ValidationType::POSTAL_CODE, R"(^\d{6}$)"}
		};

		mutable std::map<ValidationType, std::regex> compiledRegex;

	public:
		const std::regex& GetRegex(ValidationType type) const;
		ValidationResult ValidateRegex(const std::string& str, const std::string& pattern) const;
		ValidationResult Validate(const std::string& str, ValidationType type) const;
		ValidationResult ValidateLength(const std::string& str, size_t minimumLength, size_t maximumLength) const;
		ValidationResult ValidateCharset(const std::string& str, const std::string& allowedChars) const;
		ValidationResult ValidateCustom(const std::string& str, std::function<bool(const std::string&)> validator, const std::string& errorMessage = "Custom validation failed") const;
		ValidationResult ValidateMultiple(const std::string& str, const std::vector<std::pair<ValidationType, std::string>>& validations) const;
		void AddCustomPattern(ValidationType type, const std::string& pattern);
		ValidationResult ValidateEmail(const std::string& email) const;
		ValidationResult ValidatePhone(const std::string& phone) const;
		ValidationResult ValidateURL(const std::string& url) const;
		ValidationResult ValidateIPAddress(const std::string& ip) const;
		ValidationResult ValidateDate(const std::string& date) const;
		ValidationResult ValidateNumber(const std::string& number) const;
		ValidationResult ValidateInteger(const std::string& integer) const;
		ValidationResult ValidateHex(const std::string& hex) const;
		std::vector<std::pair<std::string, ValidationResult>> BatchValidate(const std::vector<std::pair<std::string, ValidationType>>& items) const;
	};
}
